package com.infra.micro.id.domain.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.infra.common.resp.PageEx;
import com.infra.common.resp.Response;
import com.infra.micro.id.domain.cache.AppCache;
import com.infra.micro.id.domain.core.snowflake.IdSnowflakeGenerator;
import com.infra.micro.id.domain.entity.IdWorkerPO;
import com.infra.micro.id.domain.service.IdWorkerService;
import com.infra.micro.id.domain.utils.IpUtils;
import com.infra.micro.id.domain.repository.IdWorkerRepository;
import com.infra.micro.id.model.req.QueryIdWorkerByCondReq;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Set;

@Service
public class IdWorkerServiceImpl extends IdSnowflakeGenerator implements IdWorkerService {
    private final AppCache appCache;

    public IdWorkerServiceImpl(IdWorkerRepository idWorkerRepository, AppCache appCache) {
        super(idWorkerRepository);
        this.appCache = appCache;
    }

    @Override
    public Long getId(Integer appId, String secretKey) {
        if (bizConfig.getEnableAuth() && !appCache.verify(appId.toString(), secretKey)) {
            throw new IllegalArgumentException("请提供正确的密钥");
        }
        return super.getId(appId);
    }

    @Override
    public Set<Long> getIds(Integer appId, int step, String secretKey) {
        if (bizConfig.getEnableAuth() && !appCache.verify(appId.toString(), secretKey)) {
            throw new IllegalArgumentException("请提供正确的密钥");
        }
        return super.getIds(appId, step);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public IdWorkerPO initWorkerServer() {
        String ip = IpUtils.getIp();
        Integer port = bizConfig.getPort();
        IdWorkerPO result = idWorkerRepository.queryByCond(ip, port);
        if (result == null) {
            result = buildIdWorkerPO(ip, port);
            idWorkerRepository.insert(result);
        } else {
            updateMaxTimestamp(result.getWorkerId());
        }

        this.workerId = result.getWorkerId();
        //2022-09-15
        this.epoch = 1663226231933L;
        this.maxTimestamp = ~(-1L << this.timestampBits) + epoch;

        return result;
    }

    @Override
    public int updateMaxTimestamp(int workerId) {
        try {
            return idWorkerRepository.updateMaxTimestamp(workerId, System.currentTimeMillis());
        } catch (Exception ex) {
            LOGGER.error("更新timestamp时出错了", ex);
            return 0;
        }
    }

    public Response<PageEx<IdWorkerPO, QueryIdWorkerByCondReq>> queryByPage(QueryIdWorkerByCondReq req) {
        PageInfo<Object> pageInfo = PageHelper.startPage(req.getPageIndex(), req.getPageSize(), StringUtils.isEmpty(req.getSortField()) ? null : req.getSortField() + " " + req.getSortType())
                .doSelectPageInfo(() -> idWorkerRepository.queryList(req));

        return Response.success(PageEx.builder(pageInfo, req), "查询成功");
    }

    private IdWorkerPO buildIdWorkerPO(String ip, Integer port) {
        IdWorkerPO record = new IdWorkerPO();
        record.setIp(ip);
        record.setPort(port);
        record.setLocalhost(String.format("%s:%s", ip, port.toString()));
        record.setMaxTimestamp(System.currentTimeMillis());
        return record;
    }
}
